package com.woniu.inlet.listen;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.rabbitmq.client.Channel;
import com.woniu.adapter.SellRateAdapter;
import com.woniu.adapter.UserDetailAdapter;
import com.woniu.inlet.vo.ConfirmCurrentSellOrder;
import com.woniu.inlet.vo.FixedInputBuyOrder;
import com.woniu.inlet.vo.FixedMsgVo;
import com.woniu.outlet.client.OrderMessage;
import com.woniu.outlet.client.UpdateOrderStatus;
import com.woniu.outlet.mysql.ReceivedMsgOrderSellCurrentPayDao;
import com.woniu.outlet.mysql.po.ReceivedMsgOrderSellCurrentPayMySQL;
import com.woniu.outlet.mysql.po.SellRateMySQL;
import com.woniu.service.UserDetailService;
import com.woniu.service.bean.AddBuyRecord;
import com.woniu.service.bean.AddEarnings;
import com.woniu.service.bean.AddSellRecord;
import com.woniu.service.domain.UserDetail;
import com.woniu.util.AppUtils;
import com.woniu.util.DateUtil;
import com.woniu.util.IsWorkingDayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;

/**
 * 获取基金的定投买入
 */
@Slf4j
@RabbitListener(queues = "order_buy_fund_fixedInput_pay")
@Component
public class FundFixedInputListener {

    @Autowired
    private ReceivedMsgOrderSellCurrentPayDao receivedMsgOrderSellCurrentPayDao;
    @Autowired
    private OrderMessage orderMessage;
    @Autowired
    private UpdateOrderStatus updateOrderStatus;
    @Autowired
    private UserDetailAdapter userDetailAdapter;

    @Transactional // 抛出异常，事务回滚。
    @RabbitHandler
    public void handle(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        String[] strings = message.split("!");
        if (strings.length < 2) {
            channel.basicReject(tag, false);
            throw new RuntimeException("接收到的消息内容格式错误");
        }

        // 消息的第一部分是：消息在【可靠消息服务】那边的消息表中的ID（唯一）。
        String messageIdString = strings[0];
        Integer messageId = Integer.parseInt(messageIdString);

        // 消息的第二部分是：订单模块发送过来的具体消息 。
        String substring = strings[1];

        try {
            // 1. 判断是否是重复消息：insert into 去重表
            receivedMsgOrderSellCurrentPayDao.insert(new ReceivedMsgOrderSellCurrentPayMySQL(null, messageId));
        } catch (RuntimeException e) {
            log.debug("该消息重复");
            // 2. 拒绝消息。要求 RabbitMQ 从队列中删除。
            channel.basicReject(tag, false);
            return;
        }
        try {
            log.debug("开始处理定投消息");
            List list = JSONArray.parseObject(substring, List.class);
            for (Object o : list) {
                FixedMsgVo fixedMsgVo = JSON.parseObject(o.toString(), FixedMsgVo.class);
                //买入id
                String id=fixedMsgVo.getId().toString();
                UserDetail user = userDetailAdapter.getUserById(fixedMsgVo.getUserId().intValue());
                if (user.getRestAmount().compareTo(new BigDecimal(fixedMsgVo.getFixedAmount())) >= 0) {
                    //余额充足，扣钱
                    deductMoney(user,fixedMsgVo);

                    //得到添加后的payId
                    int payId = addBuyRecord(fixedMsgVo);
                    //得到可撤销的日期
                    String revocationTime=revocationTime();
                    //扣钱后，feign给订单模块
                    confirmFixedInput(id,payId,revocationTime);

                    //发送通知给用户模块，告知定投已经续费成功
                    String inform = "您好，您的定投产品" + fixedMsgVo.getName() + "已成功续费。" + "-" + fixedMsgVo.getUserId() + "-" + "y";
                    orderMessage.sendMessage("pay.inform.user", "pay_inform_user", inform);
                } else {
                    //余额不足，feign给订单模块
                    confirmFixedInput(id,0,"0");

                    //发送通知给用户模块，告知余额不足
                    String inform = "您好，您购买的定投产品" + fixedMsgVo.getName() + "，订单支付时余额不足，请于14点之前充值，我们将为您再次创建订单。" + "-" + fixedMsgVo.getUserId() + "-" + "y";
                    orderMessage.sendMessage("pay.inform.user", "pay_inform_user", inform);
                }
            }
        } catch (RuntimeException e) {
            e.printStackTrace();
            // 执行本地业务出错，拒绝消息，要求 RabbitMQ 从队列中删除。
            // 等待发送者的定时器下次再发送一次。
            channel.basicReject(tag, false);
            throw new NullPointerException();
        }
    }

    /**
     * 扣钱
     */
    public void deductMoney(UserDetail user,FixedMsgVo fixedMsgVo){
        UserDetail userDetail = new UserDetail();
        userDetail.setRestAmount(user.getRestAmount().subtract(new BigDecimal(fixedMsgVo.getFixedAmount())));
        userDetail.setUserId(fixedMsgVo.getUserId().intValue());
        userDetailAdapter.updateInfo(userDetail);
    }

    /**
     * 发送定投确认消息到order
     * @param id
     * @param payId
     * @param revocationTime
     */
    public void confirmFixedInput(String id,int payId,String revocationTime){
        FixedInputBuyOrder fixedInputBuyOrder = new FixedInputBuyOrder();
        fixedInputBuyOrder.setId(id);
        fixedInputBuyOrder.setPayId(payId);
        fixedInputBuyOrder.setRevocationTime(revocationTime);
        while (true){
            try {
                updateOrderStatus.fixedInputBuyOrder(fixedInputBuyOrder);
                break;
            } catch (Exception e) {
                log.debug("定投订单确认失败，重试");
            }
        }
    }

    /**
     * 得到可撤销的日期
     *
     * @return
     */
    public String revocationTime() {
        //得到当前系统时间
        String timeStr = AppUtils.getTime();
        //判断今天是否是工作日
        String isWorkingDay = IsWorkingDayUtil.getIsWorkingDay(timeStr);
        if (isWorkingDay.equals("y")) {
            //获取当前系统时间的小时数
            String timeH = AppUtils.getTimeH();
            if (Integer.valueOf(timeH) < 15) {
                //如果当天15点之前买入则当天可以出售
                return AppUtils.getTimeg();
            }
        }
        //否者就自动计算可撤销的时间
        return DateUtil.getIncomeDate();
    }

    /**
     * 添加数据，返回id
     *
     * @param fixedMsgVo
     * @return
     */
    public int addBuyRecord(FixedMsgVo fixedMsgVo) {
        AddBuyRecord addBuyRecord = new AddBuyRecord();
        addBuyRecord.setUserId(fixedMsgVo.getUserId().intValue());
        addBuyRecord.setDealTime(AppUtils.getNowTimeStr());
        addBuyRecord.setDealPrice(new BigDecimal(fixedMsgVo.getFixedAmount()));
        //定期没有手续费
        addBuyRecord.setDealCharge(new BigDecimal(0));
        addBuyRecord.setProductType(fixedMsgVo.getProductType());
        addBuyRecord.setProductCode(fixedMsgVo.getCodeId());
        return addBuyRecord.execute();
    }

}
